package com.huanke.iot.api.service.device.basic;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Joiner;
import com.huanke.iot.api.cache.DeviceCache;
import com.huanke.iot.api.constants.DeviceAbilityTypeContants;
import com.huanke.iot.api.controller.h5.req.DeviceFuncVo;
import com.huanke.iot.api.controller.h5.req.DeviceGroupFuncVo;
import com.huanke.iot.api.controller.h5.req.ShareRequest;
import com.huanke.iot.api.controller.h5.response.DeviceAbilitysVo;
import com.huanke.iot.api.controller.h5.response.DeviceDetailVo;
import com.huanke.iot.api.controller.h5.response.DeviceShareVo;
import com.huanke.iot.api.controller.h5.response.SensorDataVo;
import com.huanke.iot.api.gateway.MqttSendService;
import com.huanke.iot.api.util.FloatDataUtil;
import com.huanke.iot.api.wechat.WechartUtil;
import com.huanke.iot.base.constant.CommonConstant;
import com.huanke.iot.base.constant.DeviceConstant;
import com.huanke.iot.base.constant.DeviceTeamConstants;
import com.huanke.iot.base.dao.customer.CustomerMapper;
import com.huanke.iot.base.dao.customer.CustomerUserMapper;
import com.huanke.iot.base.dao.customer.WxBgImgMapper;
import com.huanke.iot.base.dao.customer.WxConfigMapper;
import com.huanke.iot.base.dao.device.DeviceCustomerUserRelationMapper;
import com.huanke.iot.base.dao.device.DeviceMapper;
import com.huanke.iot.base.dao.device.DeviceTeamItemMapper;
import com.huanke.iot.base.dao.device.DeviceTeamMapper;
import com.huanke.iot.base.dao.device.ability.DeviceAbilityMapper;
import com.huanke.iot.base.dao.device.ability.DeviceAbilityOptionMapper;
import com.huanke.iot.base.dao.device.data.DeviceOperLogMapper;
import com.huanke.iot.base.dao.device.stat.DeviceSensorStatMapper;
import com.huanke.iot.base.dao.device.typeModel.DeviceModelAbilityMapper;
import com.huanke.iot.base.dao.device.typeModel.DeviceModelAbilityOptionMapper;
import com.huanke.iot.base.dao.device.typeModel.DeviceModelMapper;
import com.huanke.iot.base.dao.device.typeModel.DeviceTypeMapper;
import com.huanke.iot.base.dto.DeviceModelTeamDto;
import com.huanke.iot.base.enums.FuncTypeEnums;
import com.huanke.iot.base.enums.SensorTypeEnums;
import com.huanke.iot.base.exception.BusinessException;
import com.huanke.iot.base.po.customer.CustomerUserPo;
import com.huanke.iot.base.po.customer.WxConfigPo;
import com.huanke.iot.base.po.device.DeviceCustomerUserRelationPo;
import com.huanke.iot.base.po.device.DevicePo;
import com.huanke.iot.base.po.device.ability.DeviceAbilityOptionPo;
import com.huanke.iot.base.po.device.ability.DeviceAbilityPo;
import com.huanke.iot.base.po.device.data.DeviceOperLogPo;
import com.huanke.iot.base.po.device.stat.DeviceSensorStatPo;
import com.huanke.iot.base.po.device.team.DeviceTeamItemPo;
import com.huanke.iot.base.po.device.team.DeviceTeamPo;
import com.huanke.iot.base.po.device.typeModel.DeviceModelAbilityOptionPo;
import com.huanke.iot.base.po.device.typeModel.DeviceTypePo;
import com.huanke.iot.base.util.LocationUtils;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.assertj.core.util.Lists;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Repository
@Slf4j
public class DeviceDataService {

    private static final List<Integer> deviceIds = Arrays.asList(100276,100260,100254,100273);

    @Autowired
    private DeviceMapper deviceMapper;

    @Autowired
    private DeviceOperLogMapper deviceOperLogMapper;

    @Autowired
    private MqttSendService mqttSendService;

    @Autowired
    private DeviceTypeMapper deviceTypeMapper;

    @Autowired
    private DeviceModelMapper deviceModelMapper;

    @Autowired
    private DeviceAbilityMapper deviceAbilityMapper;

    @Autowired
    private DeviceAbilityOptionMapper deviceAbilityOptionMapper;

    @Autowired
    private CustomerUserMapper customerUserMapper;

    @Autowired
    private DeviceCustomerUserRelationMapper deviceCustomerUserRelationMapper;

    @Autowired
    private DeviceTeamItemMapper deviceTeamItemMapper;

    @Autowired
    private DeviceTeamMapper deviceTeamMapper;

    @Autowired
    private DeviceSensorStatMapper deviceSensorStatMapper;

    @Autowired
    private WxConfigMapper wxConfigMapper;

    @Autowired
    private LocationUtils locationUtils;

    @Autowired
    private CustomerMapper customerMapper;

    @Autowired
    private DeviceModelAbilityOptionMapper deviceModelAbilityOptionMapper;

    @Autowired
    private DeviceModelAbilityMapper deviceModelAbilityMapper;

    @Autowired
    private WxBgImgMapper wxBgImgMapper;

    @Autowired
    private WechartUtil wechartUtil;


    @Autowired
    private DeviceCache deviceCache;


    @Value("${unit}")
    private Integer unit;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    private static String[] modes = {"云端大数据联动", "神经网络算法", "模糊驱动算法", "深度学习算法"};

    private static final int MASTER = 1;
    private static final int SLAVE = 2;
    @Value("${speed}")
    private int speed;

    private static final String TOKEN_PREFIX = "token.";

    @Transactional
    public Object shareDevice(Integer toId, ShareRequest request) {
        Integer deviceId = request.getDeviceId();
        String master = request.getMasterOpenId();
        String token = request.getToken();
        DevicePo devicePo = deviceMapper.selectById(deviceId);

        if (devicePo == null) {
            log.error("找不到设备，deviceId={}", deviceId);
            throw new BusinessException("找不到设备");
        }
        String deviceIdStr = devicePo.getWxDeviceId();
        //通过设备查customerId
        Integer customerId = deviceMapper.getCustomerId(devicePo);
        CustomerUserPo customerUserPo = customerUserMapper.selectByOpenId(master);
        if (customerUserPo == null) {
            log.error("找不到用户，openId={}", master);
            throw new BusinessException("找不到用户");
        }
        String storeToken = stringRedisTemplate.opsForValue().get(TOKEN_PREFIX + deviceId);
        if (StringUtils.isEmpty(storeToken) || !StringUtils.equals(storeToken, token)) {
            storeToken = stringRedisTemplate.opsForValue().get(TOKEN_PREFIX + deviceIdStr);
            if (StringUtils.isEmpty(storeToken) || !StringUtils.equals(storeToken, token)) {
                throw new BusinessException("此分享已过期");
            }
        }
        if (customerUserPo.getId().equals(toId)) {
            log.error("无法给自己分享设备");
            throw new BusinessException("无法给自己分享设备");
        }

        //TODO检查deviceId和用户是不是可以对应上的
        DeviceTeamItemPo queryTeamItemPo = new DeviceTeamItemPo();
        queryTeamItemPo.setDeviceId(deviceId);
        queryTeamItemPo.setUserId(customerUserPo.getId());
        queryTeamItemPo.setStatus(1);
        Integer itemCount = deviceTeamMapper.queryItemCount(queryTeamItemPo);
        if (itemCount == 0) {
            log.error("用户组下无设备");
            throw new BusinessException("用户组下无设备");
        }
        //TODO检查deviceId和要分享用户是不是已存在
        DeviceTeamItemPo toQueryTeamItemPo = new DeviceTeamItemPo();
        toQueryTeamItemPo.setDeviceId(deviceId);
        toQueryTeamItemPo.setUserId(toId);
        toQueryTeamItemPo.setStatus(null);
        List<DeviceTeamItemPo> deviceTeamItemPoList = deviceTeamMapper.queryTeamItems(toQueryTeamItemPo);
        if (deviceTeamItemPoList.size() > 0 && deviceTeamItemPoList.get(0).getStatus().equals(CommonConstant.STATUS_YES)) {
            log.error("该用户已拥有此设备");
            throw new BusinessException("该用户已拥有此设备");
        }

        DeviceTeamPo deviceTeamPo = new DeviceTeamPo();
        String defaultTeamName = wxConfigMapper.selectConfigByCustomerId(customerId).getDefaultTeamName();
        deviceTeamPo.setName(defaultTeamName);
        deviceTeamPo.setMasterUserId(toId);
        deviceTeamPo.setCreateUserId(toId);
        deviceTeamPo.setCustomerId(customerUserPo.getCustomerId());
        deviceTeamPo.setStatus(1);
        //检查是否已经拥有默认组
        DeviceTeamPo toDeviceTeamPo = deviceTeamMapper.queryByName(deviceTeamPo);
        Integer teamId;
        if (toDeviceTeamPo != null && toDeviceTeamPo.getStatus().equals(CommonConstant.STATUS_YES)) {
            teamId = toDeviceTeamPo.getId();
        } else {
            deviceTeamPo.setCreateTime(System.currentTimeMillis());
            deviceTeamPo.setTeamStatus(1);
            deviceTeamPo.setTeamType(DeviceTeamConstants.DEVICE_TEAM_TYPE_USER);
            deviceTeamPo.setCreateUserId(toId);
            deviceTeamPo.setCustomerId(customerId);
            deviceTeamMapper.insert(deviceTeamPo);
            teamId = deviceTeamPo.getId();
        }
        if (deviceTeamItemPoList.size() > 0 && deviceTeamItemPoList.get(0).getStatus().equals(CommonConstant.STATUS_DEL)) {
            DeviceTeamItemPo deviceTeamItemPo = deviceTeamItemPoList.get(0);
            deviceTeamItemPo.setTeamId(teamId);
            deviceTeamItemPo.setLastUpdateTime(System.currentTimeMillis());
            deviceTeamItemPo.setStatus(CommonConstant.STATUS_YES);
            deviceTeamItemMapper.updateById(deviceTeamItemPo);
            return true;
        }
        DeviceTeamItemPo queryItemPo = new DeviceTeamItemPo();
        queryItemPo.setDeviceId(deviceId);
        queryItemPo.setUserId(toId);
        queryItemPo.setTeamId(teamId);
        queryItemPo.setStatus(1);
        queryItemPo.setCreateTime(System.currentTimeMillis());
        deviceTeamItemMapper.insert(queryItemPo);
        return true;
    }

    public Boolean updateRelation(String joinOpenId, Integer userId, Integer deviceId, Integer status) {
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        if (devicePo == null) {
            log.error("找不到设备，deviceId={}", deviceId);
            return false;
        }
        CustomerUserPo customerUserPo = customerUserMapper.selectById(userId);
        DeviceCustomerUserRelationPo deviceCustomerUserRelationPo = new DeviceCustomerUserRelationPo();
        deviceCustomerUserRelationPo.setOpenId(customerUserPo.getOpenId());
        deviceCustomerUserRelationPo.setDeviceId(deviceId);
        DeviceCustomerUserRelationPo byDeviceCustomerUserRelationPo = deviceCustomerUserRelationMapper.findAllByDeviceCustomerUserRelationPo(deviceCustomerUserRelationPo);
        if (byDeviceCustomerUserRelationPo == null) {
            log.error("操作人无权限，deviceId={}", deviceId);
            return false;
        }

        CustomerUserPo beClearCustomerUserPo = customerUserMapper.selectByOpenId(joinOpenId);
        if (beClearCustomerUserPo == null) {
            log.error("被更改用户不存在，deviceId={}", deviceId);
            return false;
        }
        if (beClearCustomerUserPo.getId().equals(userId)) {
            log.error("主管理员无法更改自己，deviceId={}", deviceId);
            return false;
        }
        DeviceTeamItemPo queryItemPo = new DeviceTeamItemPo();
        queryItemPo.setUserId(beClearCustomerUserPo.getId());
        queryItemPo.setDeviceId(deviceId);
        queryItemPo.setStatus(null);
        List<DeviceTeamItemPo> deviceTeamItemPos = deviceTeamMapper.queryTeamItems(queryItemPo);
        if (deviceTeamItemPos.size() == 0) {
            log.error("被更改用户无此设备，deviceId={}", deviceId);
            return false;
        }
        DeviceTeamItemPo deviceTeamItemPo = deviceTeamItemPos.get(0);
        return deviceTeamItemMapper.updateStatus(deviceTeamItemPo.getDeviceId(), deviceTeamItemPo.getUserId(), status) > 0;
    }


    public List<SensorDataVo> getHistoryData(Integer deviceId, Integer type) {
        Long startTimestamp = new DateTime().plusDays(-1).getMillis();
        Long endTimeStamp = System.currentTimeMillis();

        List<SensorDataVo> sensorDataVos = Lists.newArrayList();
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        if (devicePo == null) {
            return null;
        }
        Integer modelId = devicePo.getModelId();
        List<DeviceAbilityPo> deviceAbilityPos = deviceModelAbilityMapper.selectActiveByModelId(modelId);
        List<String> dirValues = deviceAbilityPos.stream().map(deviceAbilityPo -> deviceAbilityPo.getDirValue()).collect(Collectors.toList());
        List<DeviceSensorStatPo> deviceSensorPos = deviceSensorStatMapper.selectData(devicePo.getId(), startTimestamp, endTimeStamp);
        for (String sensorType : dirValues) {
            SensorDataVo sensorDataVo = new SensorDataVo();
            SensorTypeEnums sensorTypeEnums = SensorTypeEnums.getByCode(sensorType);
            if (sensorTypeEnums == null) {
                continue;
            }
            sensorDataVo.setName(sensorTypeEnums.getMark());
            sensorDataVo.setUnit(sensorTypeEnums.getUnit());
            sensorDataVo.setType(sensorType);
            List<String> xdata = Lists.newArrayList();
            List<String> ydata = Lists.newArrayList();
            for (DeviceSensorStatPo deviceSensorPo : deviceSensorPos) {
                if (deviceSensorPo.getPm() == null && devicePo.getHostDeviceId() == null) {
                    continue;
                }
                xdata.add(new DateTime(deviceSensorPo.getStartTime()).toString("yyyy-MM-dd HH:mm:ss"));
                switch (sensorTypeEnums){
                    case CO2_IN:
                        List<DeviceAbilityPo> collect = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.CO2_IN.getCode())).collect(Collectors.toList());
                        Double multiple = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect.get(0).getId());

                        String replace = String.format("%.2f",(Double.valueOf(deviceSensorPo.getCo2()) * (multiple ==null? 1:multiple))).replace(".00", "");
                        if(replace.contains(".") && replace.endsWith("0")){
                            replace = replace.substring(0, replace.length()-1);
                        }

                        ydata.add(replace);
                        break;
                    case HUMIDITY_IN:
                        if(deviceSensorPo.getHum() != null){
                            List<DeviceAbilityPo> collect1 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.HUMIDITY_IN.getCode())).collect(Collectors.toList());
                            Double multiple1 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect1.get(0).getId());

                            String replace1 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getHum()) * (multiple1 ==null? 1:multiple1))).replace(".00", "");
                            if(replace1.contains(".") && replace1.endsWith("0")){
                                replace1 = replace1.substring(0, replace1.length()-1);
                            }

                            ydata.add(replace1);
                            break;
                        }
                        ydata.add("0");
                        break;
                    case TEMPERATURE_IN:
                        if(deviceSensorPo.getTem() != null){
                            List<DeviceAbilityPo> collect2 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.TEMPERATURE_IN.getCode())).collect(Collectors.toList());
                            Double multiple2 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect2.get(0).getId());

                            String replace2 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getTem()) * (multiple2 ==null? 1:multiple2))).replace(".00", "");
                            if(replace2.contains(".") && replace2.endsWith("0")){
                                replace2 = replace2.substring(0, replace2.length()-1);
                            }
                            if(Double.valueOf(replace2) > 28){
                                ydata.add("28");
                            }else{
                                ydata.add(replace2);
                            }
                            break;
                        }
                        ydata.add("0");
                        break;
                    case HCHO_IN:
                        List<DeviceAbilityPo> collect3 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.HCHO_IN.getCode())).collect(Collectors.toList());
                        Double multiple3 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect3.get(0).getId());

                        String replace3 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getHcho()) * (multiple3 ==null? 1:multiple3))).replace(".00", "");
                        if(replace3.contains(".") && replace3.endsWith("0")){
                            replace3 = replace3.substring(0, replace3.length()-1);
                        }
                        //特殊处理（上海大厦）
                        if(deviceIds.contains(deviceId)){
                            //甲醛
                            Double aDouble = Double.valueOf(replace3)/3;
                            if(aDouble > 0.1){
                                aDouble = 0.1;
                            }else if(aDouble < 0.01){
                                aDouble = 0.01;
                            }
                            ydata.add(String.format("%.2f",aDouble));
                        }else{
                            ydata.add(replace3);
                        }
                        break;
                    case PM25_IN:
                        List<DeviceAbilityPo> collect4 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.PM25_IN.getCode())).collect(Collectors.toList());
                        Double multiple4 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect4.get(0).getId());

                        String replace4 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getPm()) * (multiple4 ==null? 1:multiple4))).replace(".00", "");
                        if(replace4.contains(".") && replace4.endsWith("0")){
                            replace4 = replace4.substring(0, replace4.length()-1);
                        }
                        ydata.add(replace4);
                        break;
                    case TVOC_IN:
                        List<DeviceAbilityPo> collect5 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.TVOC_IN.getCode())).collect(Collectors.toList());
                        Double multiple5 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect5.get(0).getId());

                        String replace5 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getTvoc()) * (multiple5 ==null? 1:multiple5))).replace(".00", "");
                        if(replace5.contains(".") && replace5.endsWith("0")){
                            replace5 = replace5.substring(0, replace5.length()-1);
                        }
                        //特殊处理(上海大厦)
                        if(deviceIds.contains(deviceId)){
                            //tvoc
                            Double aDouble = Double.valueOf(replace5)/2;
                            if(aDouble > 0.8){
                                aDouble = 0.8;
                            }else if(aDouble < 0.1){
                                aDouble = 0.1;
                            }
                            ydata.add(String.format("%.2f", aDouble));
                        }else{
                            ydata.add(replace5);
                        }
                        break;
                    case NH3_IN:
                        List<DeviceAbilityPo> collect6 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.NH3_IN.getCode())).collect(Collectors.toList());
                        Double multiple6 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect6.get(0).getId());

                        String replace6 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getNh3()) * (multiple6 ==null? 1:multiple6))).replace(".00", "");
                        if(replace6.contains(".") && replace6.endsWith("0")){
                            replace6 = replace6.substring(0, replace6.length()-1);
                        }
                        ydata.add(replace6);
                        break;
                    case ANION_IN:
                        List<DeviceAbilityPo> collect7 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.ANION_IN.getCode())).collect(Collectors.toList());
                        Double multiple7 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect7.get(0).getId());
                        String replace7 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getAnion()) * (multiple7 ==null? 1:multiple7))).replace(".00", "");
                        if(replace7.contains(".") && replace7.endsWith("0")){
                            replace7 = replace7.substring(0, replace7.length()-1);
                        }
                        ydata.add(replace7);
                        break;
                    case OUT_WATER_TEM:
                        if(deviceSensorPo.getOutWaterTem() != null){
                            List<DeviceAbilityPo> collect8 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.OUT_WATER_TEM.getCode())).collect(Collectors.toList());
                            Double multiple8 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect8.get(0).getId());
                            String replace8 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getOutWaterTem()) * (multiple8 ==null? 1:multiple8))).replace(".00", "");
                            if(replace8.contains(".") && replace8.endsWith("0")){
                                replace8 = replace8.substring(0, replace8.length()-1);
                            }
                            ydata.add(replace8);
                            break;
                        }
                        ydata.add("0");
                        break;
                    case AIR_TEMPERATURE:
                        if(deviceSensorPo.getInWaterTem() != null){
                            List<DeviceAbilityPo> collect9 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.AIR_TEMPERATURE.getCode())).collect(Collectors.toList());
                            Double multiple9 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect9.get(0).getId());
                            String replace9 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getInWaterTem()) * (multiple9 ==null? 1:multiple9))).replace(".00", "");
                            if(replace9.contains(".") && replace9.endsWith("0")){
                                replace9 = replace9.substring(0, replace9.length()-1);
                            }
                            ydata.add(replace9);
                            break;
                        }
                        ydata.add("0");
                        break;
                    case HUMIDITY_F:
                        if(deviceSensorPo.getHum() != null){
                            List<DeviceAbilityPo> collect10 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.HUMIDITY_F.getCode())).collect(Collectors.toList());
                            Double multiple9 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect10.get(0).getId());
                            String replace10 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getHum()) * (multiple9 ==null? 1:multiple9))).replace(".00", "");
                            if(replace10.contains(".") && replace10.endsWith("0")){
                                replace10 = replace10.substring(0, replace10.length()-1);
                            }
                            ydata.add(replace10);
                            break;
                        }
                        ydata.add("0");
                        break;
                    case PM25_F:
                        if(deviceSensorPo.getPm() != null){
                            List<DeviceAbilityPo> collect11 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.PM25_F.getCode())).collect(Collectors.toList());
                            Double multiple9 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect11.get(0).getId());
                            String replace11 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getPm()) * (multiple9 ==null? 1:multiple9))).replace(".00", "");
                            if(replace11.contains(".") && replace11.endsWith("0")){
                                replace11 = replace11.substring(0, replace11.length()-1);
                            }
                            ydata.add(replace11);
                            break;
                        }
                        ydata.add("0");
                        break;
                    case CO2_F:
                        if(deviceSensorPo.getCo2() != null){
                            List<DeviceAbilityPo> collect12 = deviceAbilityPos.stream().filter(e -> e.getDirValue().equals(SensorTypeEnums.CO2_F.getCode())).collect(Collectors.toList());
                            Double multiple9 = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, collect12.get(0).getId());
                            String replace12 = String.format("%.2f",(Double.valueOf(deviceSensorPo.getCo2()) * (multiple9 ==null? 1:multiple9))).replace(".00", "");
                            if(replace12.contains(".") && replace12.endsWith("0")){
                                replace12 = replace12.substring(0, replace12.length()-1);
                            }
                            ydata.add(replace12);
                            break;
                        }
                        ydata.add("0");
                        break;
                    default:
                        break;
                }
                sensorDataVo.setXdata(xdata);
                sensorDataVo.setYdata(ydata);
            }
            if (!ydata.isEmpty()) {
                sensorDataVos.add(sensorDataVo);
            }
            sensorDataVo.setXdata(xdata);
            sensorDataVo.setYdata(ydata);
        }
        return sensorDataVos;
    }

    public List<DeviceShareVo> shareList(Integer userId, Integer deviceId) {
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        if (devicePo != null) {
            CustomerUserPo customerUserPo = customerUserMapper.selectById(userId);
            DeviceCustomerUserRelationPo deviceCustomerUserRelationPo = new DeviceCustomerUserRelationPo();
            deviceCustomerUserRelationPo.setOpenId(customerUserPo.getOpenId());
            deviceCustomerUserRelationPo.setDeviceId(deviceId);
            DeviceCustomerUserRelationPo byDeviceCustomerUserRelationPo = deviceCustomerUserRelationMapper.findAllByDeviceCustomerUserRelationPo(deviceCustomerUserRelationPo);

            if (byDeviceCustomerUserRelationPo != null) {
                DeviceTeamItemPo deviceTeamItemPo = new DeviceTeamItemPo();
                deviceTeamItemPo.setDeviceId(deviceId);
                List<DeviceTeamItemPo> deviceTeamItemPos = deviceTeamItemMapper.selectItemsByDeviceId(deviceId);
                List<DeviceCustomerUserRelationPo> masterDeviceCustomerUserRelationPos = deviceCustomerUserRelationMapper.queryByDeviceId(deviceId);
                List<DeviceTeamItemPo> finalDeviceTeamItemPos = deviceTeamItemPos.stream().filter(deviceTeamItemPo1 -> {
                    List<String> openIdsList = masterDeviceCustomerUserRelationPos.stream().map(deviceCustomerUserRelationPo1 -> deviceCustomerUserRelationPo1.getOpenId()).collect(Collectors.toList());
                    Integer userId1 = deviceTeamItemPo1.getUserId();
                    CustomerUserPo customerUserPo1 = customerUserMapper.selectById(userId1);
                    if (!openIdsList.contains(customerUserPo1.getOpenId())) {
                        return true;
                    }
                    return false;
                }).sorted(Comparator.comparing(DeviceTeamItemPo::getCreateTime)).collect(Collectors.toList());
                List<DeviceShareVo> shareVos = finalDeviceTeamItemPos.stream()
                        .map(finalDeviceTeamItemPo -> {
                            Integer deviceUserId = finalDeviceTeamItemPo.getUserId();
                            CustomerUserPo deviceCustomerUserPo = customerUserMapper.selectById(deviceUserId);
                            DeviceShareVo deviceShareVo = new DeviceShareVo();
                            deviceShareVo.setUserId(deviceCustomerUserPo.getId());
                            deviceShareVo.setNickname(deviceCustomerUserPo.getNickname());
                            deviceShareVo.setJoinTime(finalDeviceTeamItemPo.getCreateTime());
                            deviceShareVo.setOpenId(deviceCustomerUserPo.getOpenId());
                            deviceShareVo.setHeadImg(deviceCustomerUserPo.getHeadimgurl());
                            deviceShareVo.setStatus(finalDeviceTeamItemPo.getStatus() == 1 ? true : false);
                            return deviceShareVo;
                        }).collect(Collectors.toList());

                return shareVos;
            }
        }
        return Lists.newArrayList();
    }

    @Transactional
    public Boolean deleteDevice(Integer userId, Integer deviceId) {
        if (deviceId == null) {
            log.error("deviceId不能为空");
            return false;
        }
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        if (devicePo == null) {
            log.error("找不到此设备");
            return false;
        }
        Boolean ret = false;

        Integer iDeviceId = devicePo.getId();

        CustomerUserPo customerUserPo = customerUserMapper.selectById(userId);
        DeviceCustomerUserRelationPo querydeviceCustomerUserRelationPo = new DeviceCustomerUserRelationPo();
        String openId = customerUserPo.getOpenId();
        querydeviceCustomerUserRelationPo.setOpenId(openId);
        querydeviceCustomerUserRelationPo.setDeviceId(iDeviceId);
        DeviceCustomerUserRelationPo deviceCustomerUserRelationPo = deviceCustomerUserRelationMapper.findAllByDeviceCustomerUserRelationPo(querydeviceCustomerUserRelationPo);
        if (deviceCustomerUserRelationPo == null) {
            log.error("找不到绑定关系, userId={}, deviceId={}, openId={}", userId, deviceId, openId);
            return false;
        }

        if (deviceCustomerUserRelationPo.getParentOpenId() == null) {
            //主控制人
            log.info("主控制人解绑设备，userId={}, deviceId={}", userId, deviceId);
            ret = deviceCustomerUserRelationMapper.deleteRelationByJoinId(openId, iDeviceId) > 0;
            ret = ret && deviceTeamItemMapper.deleteByJoinId(iDeviceId, userId) > 0;
            //deviceGroupItemMapper.deleteByJoinId(iDeviceId, userId);
        } else {
            ret = deviceCustomerUserRelationMapper.deleteRelationByJoinId(customerUserPo.getOpenId(), iDeviceId) > 0;
            ret = ret && deviceTeamItemMapper.deleteByJoinId(iDeviceId, userId) > 0;
            //deviceGroupItemMapper.deleteByJoinId(iDeviceId, userId);
        }
        return ret;
    }

    /**
     * 查询设备功能项值
     *
     * @param abilityIds
     * @return
     */
    public List<DeviceAbilitysVo> queryDetailAbilitysValue(Integer deviceId, List<Integer> abilityIds) {
        Long t1 = System.currentTimeMillis();

        DevicePo devicePo = deviceCache.get(deviceId);
        Integer modelId = devicePo.getModelId();
        boolean isOld = devicePo.getOld() == 1;
        List<DeviceAbilitysVo> deviceAbilitysVoList = new ArrayList<>();
        Map<Object, Object> datas = stringRedisTemplate.opsForHash().entries("sensor2." + deviceId);
        Map<Object, Object> controlDatas = stringRedisTemplate.opsForHash().entries("control2." + deviceId);
        //缓存功能项集
        List<DeviceAbilityPo> deviceAbilityPoCaches = deviceAbilityMapper.selectList(new DeviceAbilityPo(), 10000, 0);
        Map<Integer,DeviceAbilityPo> deviceAbilityPoMap = deviceAbilityPoCaches.stream().collect(Collectors.toMap(DeviceAbilityPo::getId, a -> a,(k1, k2)->k1));
        for (Integer abilityId : abilityIds) {
            List<DeviceModelAbilityOptionPo> deviceModelAbilityOptionPoCaches = new ArrayList<>();
            Map<Integer, DeviceModelAbilityOptionPo> deviceModelAbilityOptionPoMap = new HashMap<>();
            DeviceAbilityPo deviceabilityPo = deviceAbilityPoMap.get(abilityId);
            String dirValue = deviceabilityPo.getDirValue();
            Integer abilityType = deviceabilityPo.getAbilityType();
            DeviceAbilitysVo deviceAbilitysVo = new DeviceAbilitysVo();
            deviceAbilitysVo.setAbilityName(deviceabilityPo.getAbilityName());
            deviceAbilitysVo.setId(abilityId);
            deviceAbilitysVo.setAbilityType(abilityType);
            deviceAbilitysVo.setDirValue(dirValue);
            switch (abilityType) {
                case DeviceAbilityTypeContants.ability_type_text:
                    Double multiple = deviceModelAbilityMapper.selectMultipleByModelIdAndDirValue(modelId, abilityId);
                    if(!isOld){
                        String data = getData(controlDatas, dirValue);
//                        if(modelId == 261 && (dirValue.equals("2DD.0") || dirValue.equals("FDWD"))){//临时特殊处理海林温控器
//                            deviceAbilitysVo.setCurrValue(String.valueOf(Math.round(Double.valueOf(data)/256)));
//                            deviceAbilitysVo.setUnit(deviceabilityPo.getRemark());
//                        }else if(modelId == 261 && dirValue.equals("140")){
//                            deviceAbilitysVo.setCurrValue(String.valueOf(Math.round(Double.valueOf(data)/25.6)));
//                            deviceAbilitysVo.setUnit(deviceabilityPo.getRemark());
//                        }else{
                        String replace;
                        if (!StringUtils.isEmpty(data) && !"null".equals(data)){
                            replace = String.format("%.2f", (Double.valueOf(data) * (multiple == null ? 1 : multiple))).replace(".00", "");
                            if(replace.contains(".") && replace.endsWith("0")){
                                replace = replace.substring(0, replace.length()-1);
                            }
                        }else {
                            replace = null;
                        }
                        //特殊处理
                        List<Integer> deviceIds = new ArrayList<>();
                        Collections.addAll(deviceIds, 100276,100260,100254,100273);
                        if(deviceIds.contains(deviceId) && dirValue.equals("150")){
                            //tvoc
                            Double aDouble = Double.valueOf(replace)/2;
                            if(aDouble > 0.8){
                                aDouble = 0.8;
                            }else if(aDouble < 0.1){
                                aDouble = 0.1;
                            }
                            deviceAbilitysVo.setCurrValue(String.format("%.2f", aDouble));
                        }else if(deviceIds.contains(deviceId)  && dirValue.equals("160")){
                            //甲醛
                            Double aDouble = Double.valueOf(replace)/3;
                            if(aDouble > 0.1){
                                aDouble = 0.1;
                            }else if(aDouble < 0.01){
                                aDouble = 0.01;
                            }
                            deviceAbilitysVo.setCurrValue(String.format("%.2f", aDouble));
                        }else{
                            deviceAbilitysVo.setCurrValue(replace);
                        }
                        deviceAbilitysVo.setUnit(deviceabilityPo.getRemark());
//                        }
                    }else {
                        if (deviceabilityPo.getWriteStatus() == 1) {
                            String data = getData(controlDatas, dirValue);
                            if (data.equals("0")) {
                                data = getData(datas, dirValue);
                            }
                            String replace;
                            if (!StringUtils.isEmpty(data) && !"null".equals(data)){
                                replace = String.format("%.2f", (Double.valueOf(data) * (multiple ==null? 1:multiple))).replace(".00", "");
                                if(replace.contains(".") && replace.endsWith("0")){
                                    replace = replace.substring(0, replace.length()-1);
                                }
                            }else {
                                replace = null;
                            }
                            deviceAbilitysVo.setCurrValue(replace);
                            deviceAbilitysVo.setUnit(deviceabilityPo.getRemark());

                        } else {
                            String data = getData(datas, dirValue);
                            String replace;
                            if (!StringUtils.isEmpty(data) && !"null".equals(data)){
                                replace = String.format("%.2f",(Double.valueOf(data) * (multiple ==null? 1:multiple))).replace(".00", "");
                                if(replace.contains(".") && replace.endsWith("0")){
                                    replace = replace.substring(0, replace.length()-1);
                                }
                            }else {
                                replace = null;
                            }
                            deviceAbilitysVo.setCurrValue(replace);
                            deviceAbilitysVo.setUnit(deviceabilityPo.getRemark());
                        }
                    }
                    break;
                case DeviceAbilityTypeContants.ability_type_single:
                    List<DeviceAbilityOptionPo> deviceabilityOptionPos = deviceAbilityOptionMapper.selectOptionsByAbilityId(abilityId);
                    //缓存
                    deviceModelAbilityOptionPoCaches = deviceModelAbilityOptionMapper.queryByModelIdAbilityId(modelId ,abilityId );
                    deviceModelAbilityOptionPoMap = deviceModelAbilityOptionPoCaches.stream().collect(Collectors.toMap(DeviceModelAbilityOptionPo::getAbilityOptionId, a -> a, (k1, k2) -> k1));
                    String optionValue = getData(controlDatas, dirValue);
                    List<DeviceAbilitysVo.AbilityOption> abilityOptionList = new ArrayList<>();
                    for (DeviceAbilityOptionPo deviceabilityOptionPo : deviceabilityOptionPos) {
                        DeviceModelAbilityOptionPo deviceModelAbilityOptionPo = deviceModelAbilityOptionPoMap.get(deviceabilityOptionPo.getId());
                        if(deviceModelAbilityOptionPo == null){
                            continue;
                        }
                        DeviceAbilitysVo.AbilityOption abilityOption = new DeviceAbilitysVo.AbilityOption();
                        abilityOption.setDirValue(deviceabilityOptionPo.getOptionValue());
                        if("C3K1".equals(dirValue) || "C3K2".equals(dirValue)){
                            optionValue = optionValue.split("\\.")[0];
                        }
                        if ((StringUtils.isNotEmpty(deviceModelAbilityOptionPo.getActualOptionValue())&&optionValue.equals(deviceModelAbilityOptionPo.getActualOptionValue()))
                                ||(StringUtils.isEmpty(deviceModelAbilityOptionPo.getActualOptionValue())&&optionValue.equals(deviceabilityOptionPo.getOptionValue()))) {
                            deviceAbilitysVo.setCurrValue(deviceabilityOptionPo.getOptionValue());
                            abilityOption.setIsSelect(1);
                        } else {
                            abilityOption.setIsSelect(0);
                        }
                        abilityOptionList.add(abilityOption);
                    }
                    deviceAbilitysVo.setAbilityOptionList(abilityOptionList);
                    break;
                case DeviceAbilityTypeContants.ability_type_checkbox:
                    List<DeviceAbilityOptionPo> deviceabilityOptionPos1 = deviceAbilityOptionMapper.selectOptionsByAbilityId(abilityId);
                    //缓存
                    deviceModelAbilityOptionPoCaches = deviceModelAbilityOptionMapper.queryByModelIdAbilityId(modelId ,abilityId );
                    deviceModelAbilityOptionPoMap = deviceModelAbilityOptionPoCaches.stream().collect(Collectors.toMap(DeviceModelAbilityOptionPo::getAbilityOptionId, a -> a, (k1, k2) -> k1));
                    List<DeviceAbilitysVo.AbilityOption> abilityOptionList1 = new ArrayList<>();
                    for (DeviceAbilityOptionPo deviceabilityOptionPo : deviceabilityOptionPos1) {
                        DeviceModelAbilityOptionPo deviceModelAbilityOptionPo = deviceModelAbilityOptionPoMap.get(deviceabilityOptionPo.getId());
                        if(deviceModelAbilityOptionPo == null){
                            continue;
                        }
                        String targetOptionValue = deviceabilityOptionPo.getOptionValue();
                        String finalOptionValue = getData(controlDatas, targetOptionValue);
                        DeviceAbilitysVo.AbilityOption abilityOption = new DeviceAbilitysVo.AbilityOption();
                        abilityOption.setDirValue(deviceabilityOptionPo.getOptionValue());
                        if (Integer.valueOf(finalOptionValue) == 1) {
                            abilityOption.setIsSelect(1);
                        } else {
                            abilityOption.setIsSelect(0);
                        }
                        abilityOptionList1.add(abilityOption);
                    }
                    deviceAbilitysVo.setAbilityOptionList(abilityOptionList1);
                    break;
                case DeviceAbilityTypeContants.ability_type_threshhold:
                    deviceAbilitysVo.setCurrValue(getData(controlDatas, dirValue));
                    deviceAbilitysVo.setUnit(deviceabilityPo.getRemark());
                    break;
                case DeviceAbilityTypeContants.ability_type_threshholdselect:
                    DeviceAbilityPo deviceAbilityPo = deviceAbilityMapper.selectById(abilityId);
                    if (deviceAbilityPo.getDirValue().equals("-1")) {//滤网临时妥协办法，后期再想更优方式
                        List<DeviceAbilityOptionPo> deviceabilityOptionPos5 = deviceAbilityOptionMapper.selectOptionsByAbilityId(abilityId);
                        List<DeviceAbilitysVo.AbilityOption> abilityOptionList5 = new ArrayList<>();
                        for (DeviceAbilityOptionPo deviceabilityOptionPo : deviceabilityOptionPos5) {
                            String optionValue5 = getData(controlDatas, deviceabilityOptionPo.getOptionValue());
                            DeviceAbilitysVo.AbilityOption abilityOption = new DeviceAbilitysVo.AbilityOption();
                            abilityOption.setDirValue(deviceabilityOptionPo.getOptionValue());
                            abilityOption.setCurrValue(optionValue5);
                            abilityOptionList5.add(abilityOption);
                        }
                        deviceAbilitysVo.setAbilityOptionList(abilityOptionList5);
                    } else {
                        List<DeviceAbilityOptionPo> deviceabilityOptionPos5 = deviceAbilityOptionMapper.selectOptionsByAbilityId(abilityId);
                        //缓存
                        deviceModelAbilityOptionPoCaches = deviceModelAbilityOptionMapper.queryByModelIdAbilityId(modelId ,abilityId );
                        deviceModelAbilityOptionPoMap = deviceModelAbilityOptionPoCaches.stream().collect(Collectors.toMap(DeviceModelAbilityOptionPo::getAbilityOptionId, a -> a, (k1, k2) -> k1));
                        String optionValue5 = getData(controlDatas, dirValue);
                        List<DeviceAbilitysVo.AbilityOption> abilityOptionList5 = new ArrayList<>();
                        for (DeviceAbilityOptionPo deviceabilityOptionPo : deviceabilityOptionPos5) {
                            DeviceModelAbilityOptionPo deviceModelAbilityOptionPo = deviceModelAbilityOptionPoMap.get(deviceabilityOptionPo.getId());
                            if(deviceModelAbilityOptionPo == null){
                                continue;
                            }
                            DeviceAbilitysVo.AbilityOption abilityOption = new DeviceAbilitysVo.AbilityOption();
                            abilityOption.setDirValue(deviceabilityOptionPo.getOptionValue());
                            if (optionValue5.equals(deviceabilityOptionPo.getOptionValue())) {
                                abilityOption.setIsSelect(1);
                            } else {
                                abilityOption.setIsSelect(0);
                            }
                            abilityOptionList5.add(abilityOption);
                        }
                        deviceAbilitysVo.setAbilityOptionList(abilityOptionList5);
                    }
                    break;
                default:
                    break;

            }

            deviceAbilitysVoList.add(deviceAbilitysVo);


        }
//        //添加空气质量判定
//        if (datas.containsKey(SensorTypeEnums.PM25_IN.getCode())) {
//            DeviceAbilitysVo deviceAbilitysVo = new DeviceAbilitysVo();
//            deviceAbilitysVo.setDirValue("0");
//            deviceAbilitysVo.setAbilityName("空气质量");
//
//            String data = getData(datas, SensorTypeEnums.PM25_IN.getCode());
//            if (StringUtils.isNotEmpty(data)) {
//                Integer diData = Integer.valueOf(data);
//                if (diData >= 0 && diData <= 35) {
//                    deviceAbilitysVo.setCurrValue("优");
//                } else if (diData > 35 && diData <= 75) {
//                    deviceAbilitysVo.setCurrValue("良");
//                } else if (diData > 75 && diData <= 150) {
//                    deviceAbilitysVo.setCurrValue("中");
//                } else {
//                    deviceAbilitysVo.setCurrValue("差");
//                }
//            } else {
//                deviceAbilitysVo.setCurrValue("优");
//            }
//            deviceAbilitysVoList.add(deviceAbilitysVo);
//        }
        Long t2 = System.currentTimeMillis();
        //log.info("queryDetailAbilitysValue cost {}",(t2-t1));
        //桃浦智创城数据处理
        List<DeviceAbilitysVo> deviceAbilitysVos = taopuDatas(deviceId, deviceAbilitysVoList);
        return deviceAbilitysVos;
    }

    private List<DeviceAbilitysVo> taopuDatas(Integer deviceId, List<DeviceAbilitysVo> deviceAbilitysVo) {
        List<Integer> taopuOIDList = Arrays.asList(223,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240);
        if(taopuOIDList.contains(deviceId)){
            String jsonResult = "[{\"id\":1,\"dirValue\":\"110\",\"abilityName\":\"PM2.5\",\"abilityType\":1,\"currValue\":\"1\",\"unit\":\"PM2.5传感器-标准功能项  单位  ug/m3\",\"abilityOptionList\":null},{\"id\":2,\"dirValue\":\"120\",\"abilityName\":\"CO2\",\"abilityType\":1,\"currValue\":\"400\",\"unit\":\"室内二氧化碳传感器-标准功能项  单位PPM\",\"abilityOptionList\":null},{\"id\":3,\"dirValue\":\"130\",\"abilityName\":\"湿度\",\"abilityType\":1,\"currValue\":\"44\",\"unit\":\"室内湿度传感器-标准功能项  单位%\",\"abilityOptionList\":null},{\"id\":4,\"dirValue\":\"140\",\"abilityName\":\"温度\",\"abilityType\":1,\"currValue\":\"24\",\"unit\":\"室内温度传感器-标准功能项   单位： °C\",\"abilityOptionList\":null},{\"id\":5,\"dirValue\":\"150\",\"abilityName\":\"VOC\",\"abilityType\":1,\"currValue\":\"0.11\",\"unit\":\"室内VOC传感器-标准功能项   单位：mg/m3\",\"abilityOptionList\":null},{\"id\":6,\"dirValue\":\"160\",\"abilityName\":\"甲醛\",\"abilityType\":1,\"currValue\":\"0.02\",\"unit\":\"室内甲醛传感器-标准功能项  单位：mg/m3\",\"abilityOptionList\":null},{\"id\":11,\"dirValue\":\"270\",\"abilityName\":\"童锁\",\"abilityType\":2,\"currValue\":\"0\",\"unit\":null,\"abilityOptionList\":[{\"dirValue\":\"0\",\"isSelect\":1,\"currValue\":null},{\"dirValue\":\"1\",\"isSelect\":0,\"currValue\":null}]},{\"id\":41,\"dirValue\":\"2C0\",\"abilityName\":\"电源开关\",\"abilityType\":2,\"currValue\":\"0\",\"unit\":null,\"abilityOptionList\":[{\"dirValue\":\"1\",\"isSelect\":0,\"currValue\":null},{\"dirValue\":\"0\",\"isSelect\":1,\"currValue\":null}]}]";
            List<DeviceAbilitysVo> deviceAbilitysVos = JSONArray.parseArray(jsonResult, DeviceAbilitysVo.class);
            Random random = new Random();
            for (DeviceAbilitysVo abilitysVo : deviceAbilitysVos) {
                String dirValue = abilitysVo.getDirValue();
                switch (dirValue) {
                    case "110": //PM2.5
                        Integer i1 = random.nextInt(8) + 1;
                        abilitysVo.setCurrValue(i1.toString());
                        break;
                    case "120": //CO2
                        Integer i2 = random.nextInt(100) + 400;
                        abilitysVo.setCurrValue(i2.toString());
                        break;
                    case "130":
                        Integer i3 = random.nextInt(5) + 40;
                        abilitysVo.setCurrValue(i3.toString());
                        break;
                    case "140":
                        Integer i4 = random.nextInt(4) + 24;
                        abilitysVo.setCurrValue(i4.toString());
                        break;
                    case "150":
                        Integer i5 = random.nextInt(10) + 10;
                        double d1 = i5 * 0.01;
                        abilitysVo.setCurrValue(String.format("%.2f", d1));
                        break;
                    case "160":
                        Integer i6 = random.nextInt(5) + 1;
                        double d2 = i6 * 0.01;
                        abilitysVo.setCurrValue(String.format("%.2f", d2));
                        break;
                    default:
                        break;
                }
            }
            return deviceAbilitysVos;
        }else{
            return deviceAbilitysVo;
        }
    }

    public Boolean updateAllRelation(Integer deviceId, Integer status) {
        List<DeviceTeamItemPo> deviceTeamItemPos = deviceTeamItemMapper.selectItemsByDeviceId(deviceId);
        List<DeviceCustomerUserRelationPo> deviceCustomerUserRelationPos = deviceCustomerUserRelationMapper.queryByDeviceId(deviceId);
        List<DeviceTeamItemPo> finalDeviceTeamItemPos = deviceTeamItemPos.stream().filter(deviceTeamItemPo -> {
            List<String> openIdsList = deviceCustomerUserRelationPos.stream().map(deviceCustomerUserRelationPo -> deviceCustomerUserRelationPo.getOpenId()).collect(Collectors.toList());
            Integer userId = deviceTeamItemPo.getUserId();
            CustomerUserPo customerUserPo = customerUserMapper.selectById(userId);
            if (!openIdsList.contains(customerUserPo.getOpenId())) {
                return true;
            }
            return false;
        }).collect(Collectors.toList());
        for (DeviceTeamItemPo deviceTeamItemPo : finalDeviceTeamItemPos) {
            deviceTeamItemPo.setStatus(status);
            deviceTeamItemMapper.updateById(deviceTeamItemPo);
        }
        return true;
    }

    public Boolean clearRelation(String openId, Integer userId, Integer deviceId) {
        DeviceTeamItemPo queryItemPo = new DeviceTeamItemPo();
        CustomerUserPo beClearCustomerUserPo = customerUserMapper.selectByOpenId(openId);
        queryItemPo.setUserId(beClearCustomerUserPo.getId());
        queryItemPo.setDeviceId(deviceId);
        queryItemPo.setStatus(null);
        List<DeviceTeamItemPo> deviceTeamItemPos = deviceTeamMapper.queryTeamItems(queryItemPo);
        if (deviceTeamItemPos.size() == 0) {
            log.error("被删除用户无此设备，deviceId={}", deviceId);
            return false;
        }
        DeviceTeamItemPo deviceTeamItemPo = deviceTeamItemPos.get(0);
        return deviceTeamItemMapper.deleteByJoinId(deviceTeamItemPo.getDeviceId(), deviceTeamItemPo.getUserId()) > 0;
    }

    public Map<String, String> queryStrainerData(Integer deviceId, List<String> dirValueList) {
        Map<String, String> strainerMap = new HashMap<>();
        Map<Object, Object> controlDatas = stringRedisTemplate.opsForHash().entries("control2." + deviceId);
        for (String dirValue : dirValueList) {
            String optionValue = getData(controlDatas, dirValue);
            strainerMap.put(dirValue, optionValue);
        }
        return strainerMap;
    }

    public String queryServerUser(Integer userId) {
        CustomerUserPo customerUserPo = customerUserMapper.selectById(userId);
        WxConfigPo wxConfigPo = wxConfigMapper.selectConfigByCustomerId(customerUserPo.getCustomerId());
        return wxConfigPo.getServiceUser();
    }

    @Transactional
    public Boolean deleteDeviceItem(Integer userId, String openId, Integer deviceId) throws Exception {
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        DeviceCustomerUserRelationPo deviceCustomerUserRelationPo = new DeviceCustomerUserRelationPo();
        deviceCustomerUserRelationPo.setDeviceId(deviceId);
        deviceCustomerUserRelationPo.setOpenId(openId);
        DeviceCustomerUserRelationPo byDeviceCustomerUserRelationPo = deviceCustomerUserRelationMapper.findAllByDeviceCustomerUserRelationPo(deviceCustomerUserRelationPo);
        if(byDeviceCustomerUserRelationPo != null){
            //主用户删除微信绑定关系
            Boolean aBoolean = deleteDevice(userId, deviceId);
            Map<String, String> requestMap = new HashMap<>();
            requestMap.put("OpenID", openId);
            requestMap.put("DeviceID", devicePo.getWxDeviceId());
            requestMap.put("status", "huanke");
            //同步更新设备状态
            devicePo.setBindStatus(DeviceConstant.BIND_STATUS_NO);
            devicePo.setBindTime(null);
            deviceMapper.updateById(devicePo);
            aBoolean = aBoolean && wechartUtil.unbindDevice(openId, devicePo.getWxDeviceId());
            return aBoolean;
        }else{
            //从用户只需要删除环可绑定关系
            return deviceTeamItemMapper.deleteByJoinId(deviceId, userId) > 0;
        }
    }

    public List<String> queryBgImgs(Integer customerId) {
        List<String> bgImgs = wxBgImgMapper.queryBgImgs(customerId);
        return bgImgs;
    }


    @Data
    public static class FuncItemMessage {
        private String type;
        private String value;
        private String childid;

    }

    @Data
    public static class FuncListMessage {
        private String msg_id;
        private String msg_type;
        private List<DeviceDataService.FuncItemMessage> datas;
    }

    public DeviceDetailVo queryDetailByDeviceId(String deviceId) {
        DeviceDetailVo deviceDetailVo = new DeviceDetailVo();
        DevicePo devicePo = deviceMapper.selectByWxDeviceId(deviceId);

        if (devicePo != null) {
            deviceDetailVo.setDeviceName(devicePo.getName());
            deviceDetailVo.setDeviceId(deviceId);
            DeviceTypePo deviceTypePo = deviceTypeMapper.selectById(devicePo.getTypeId());
            if (deviceTypePo != null) {
                deviceDetailVo.setDeviceTypeName(deviceTypePo.getName());
            }

            deviceDetailVo.setIp(devicePo.getIp());
            deviceDetailVo.setMac(devicePo.getMac());
            deviceDetailVo.setDate(new DateTime().toString("yyyy年MM月dd日"));
            getIndexData(deviceDetailVo, devicePo.getId(), devicePo.getTypeId());
            if (deviceDetailVo.getPm() == null || StringUtils.isEmpty(deviceDetailVo.getPm().getData()) || StringUtils.equals("0", deviceDetailVo.getPm().getData())) {
                deviceDetailVo.setAqi("0");
            } else {
                Integer pm = Integer.valueOf(deviceDetailVo.getPm().getData());
                deviceDetailVo.setAqi(String.valueOf(getAqi(pm)));
            }
            fillDeviceInfo(deviceDetailVo, devicePo);
        }

        JSONObject weatherJson = locationUtils.getWeather(devicePo.getIp(), false);
        if (weatherJson != null) {
            if (weatherJson.containsKey("result")) {
                JSONObject result = weatherJson.getJSONObject("result");
                if (result != null) {
                    deviceDetailVo.setOuterHum(result.getString("humidity"));
                    deviceDetailVo.setOuterPm(result.getString("aqi"));
                    deviceDetailVo.setOuterTem(result.getString("temperature_curr"));
                    deviceDetailVo.setWeather(result.getString("weather_curr"));
                }
            }
        }
        if (StringUtils.isEmpty(devicePo.getLocation())) {
            JSONObject locationJson = locationUtils.getLocation(devicePo.getIp(), false);
            if (locationJson != null) {
                if (locationJson.containsKey("content")) {
                    JSONObject content = locationJson.getJSONObject("content");
                    if (content != null) {
                        if (content.containsKey("address_detail")) {
                            JSONObject addressDetail = content.getJSONObject("address_detail");
                            if (addressDetail != null) {
                                deviceDetailVo.setProvince(addressDetail.getString("province"));
                                deviceDetailVo.setCity(addressDetail.getString("city"));
                                deviceDetailVo.setArea(deviceDetailVo.getCity());
                                deviceDetailVo.setLocation(deviceDetailVo.getProvince() + "," + deviceDetailVo.getCity());
                            }
                        }
                    }
                }
            }
        } else {
            String[] locationArray = devicePo.getLocation().split(",");
            deviceDetailVo.setArea(Joiner.on(" ").join(locationArray));
            deviceDetailVo.setLocation(devicePo.getLocation());
        }
        return deviceDetailVo;
    }

    private void fillDeviceInfo(DeviceDetailVo deviceDetailVo, DevicePo devicePo) {
        DeviceDetailVo.DeviceInfoItem info = new DeviceDetailVo.DeviceInfoItem();
        info.setDeviceSupport("环可科技");
        info.setSoftSupport("环可科技");
        info.setMac(devicePo.getMac());
        info.setId(devicePo.getId());
        String version = devicePo.getVersion();
        JSONObject jsonObject = JSON.parseObject(version);
        if (jsonObject != null) {
            info.setHardVersion(jsonObject.getString("hardware"));
            info.setSoftVersion(jsonObject.getString("software"));
        }
        deviceDetailVo.setDeviceInfoItem(info);
    }

    public void sendGroupFunc(DeviceGroupFuncVo deviceGroupFuncVo, Integer userId, int operType) {
        List<Integer> deviceIdList = deviceGroupFuncVo.getDeviceIdList();
        String funcId = deviceGroupFuncVo.getFuncId();
        String value = deviceGroupFuncVo.getValue();
        for (Integer deviceId : deviceIdList) {
            DeviceFuncVo deviceFuncVo = new DeviceFuncVo();
            deviceFuncVo.setDeviceId(deviceId);
            deviceFuncVo.setFuncId(funcId);
            deviceFuncVo.setValue(value);
            String requestId = sendFunc(deviceFuncVo, userId, operType);
        }
    }

    public Boolean sendFuncs(DeviceFuncVo deviceFuncVo, Integer userId, Integer operType){
        //获取当前登录的用户
        DevicePo devicePo = deviceMapper.selectById(deviceFuncVo.getDeviceId());
        if(null != devicePo){
            //设备禁用，禁止发送指令
            if(devicePo.getEnableStatus() == DeviceConstant.ENABLE_STATUS_NO){
                throw new BusinessException("设备已禁止使用");
            }
            //对当前设备发送指令
            sendFunc(deviceFuncVo,userId,operType);
            //查看此功能项是否为群控功能
            String funcId = deviceFuncVo.getFuncId();

            DeviceModelTeamDto deviceModelTeamDto = deviceModelAbilityMapper.selectIsTeamAbilityByModelIdAndDirValue(devicePo.getModelId(), funcId);
            if(deviceModelTeamDto != null){
                String mapDirValue = deviceModelTeamDto.getMapDirValue();
                List<DeviceTeamItemPo> deviceTeamItemPos = deviceTeamItemMapper.selectByTeamId(deviceFuncVo.getTeamId());
                for (DeviceTeamItemPo deviceTeamItemPo : deviceTeamItemPos) {
                    Integer mapDeviceId = deviceTeamItemPo.getDeviceId();
                    DeviceFuncVo deviceFuncVo1 = new DeviceFuncVo();
                    BeanUtils.copyProperties(deviceFuncVo, deviceFuncVo1);
                    String dirValue = deviceModelAbilityMapper.selectDirValueByMapDirValue(mapDeviceId, mapDirValue);
                    if(dirValue == null){
                        continue;
                    }
                    deviceFuncVo1.setDeviceId(mapDeviceId);
                    deviceFuncVo1.setFuncId(dirValue);
                    sendFunc(deviceFuncVo1,userId,operType);
                }
            }
            //查询当前设备是否为联动设备
            DeviceTeamItemPo deviceTeamItemPo = this.deviceTeamItemMapper.selectByDeviceId(devicePo.getId());
            if(null != deviceTeamItemPo && deviceTeamItemPo.getLinkAgeStatus().equals(1)){
                //对其他联动设备发送指令
                List<DeviceTeamItemPo> deviceTeamItemPoList = this.deviceTeamItemMapper.selectLinkDevice(deviceTeamItemPo);
                for (DeviceTeamItemPo eachPo : deviceTeamItemPoList) {
                    DeviceFuncVo linkDeviceFuncVo = new DeviceFuncVo();
                    linkDeviceFuncVo.setDeviceId(eachPo.getDeviceId());
                    linkDeviceFuncVo.setFuncId(deviceFuncVo.getFuncId());
                    linkDeviceFuncVo.setValue(deviceFuncVo.getValue());
                    String requestId = sendFunc(linkDeviceFuncVo,userId, operType);
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 发送指令
     * @param deviceFuncVo
     * @param userId
     * @param operType
     * @return
     */
    public String sendFunc(DeviceFuncVo deviceFuncVo, Integer userId, Integer operType) {
        DevicePo devicePo = deviceMapper.selectById(deviceFuncVo.getDeviceId());
        String funcId = deviceFuncVo.getFuncId();
        Integer modelId = devicePo.getModelId();
        if (devicePo != null) {
            //对设备实际的指令值进行映射
            List<DeviceAbilityPo> deviceAbilityPos = deviceModelAbilityMapper.selectActiveByModelId(modelId);
            List<DeviceAbilityOptionPo> deviceAbilityOptionPos = new ArrayList<>();
            List<DeviceModelAbilityOptionPo> deviceModelAbilityOptionPos = new ArrayList<>();
            deviceAbilityPos.stream().filter(temp ->{return temp.getDirValue().equals(funcId);}).forEach(deviceAbilityPo-> {
                deviceAbilityOptionPos.addAll(deviceAbilityOptionMapper.selectActiveOptionsByAbilityId(deviceAbilityPo.getId()));
                deviceModelAbilityOptionPos.addAll(deviceModelAbilityOptionMapper.queryByModelIdAbilityId(modelId, deviceAbilityPo.getId()));
            });
            if(deviceAbilityPos.size()==0 && deviceAbilityOptionPos.size()==0){
                //该设备没有此功能
                return null;
            }
            Integer optionId = null;
            String actualValue = deviceFuncVo.getValue();
            if(modelId == 261 && (funcId.equals("2DD.0") || funcId.equals("FDWD"))){//临时特殊处理海林温控器
                actualValue = String.valueOf(Math.round(Double.valueOf(actualValue) * 256));
            }
            for (DeviceAbilityOptionPo temp : deviceAbilityOptionPos){
                if (deviceFuncVo.getValue().equals(temp.getOptionValue())){
                    optionId = temp.getId();
                    break;
                }
            }
            for (DeviceModelAbilityOptionPo temp : deviceModelAbilityOptionPos){
                if (temp.getAbilityOptionId().equals(optionId)&&StringUtils.isNotEmpty(temp.getActualOptionValue())){
                    actualValue = temp.getActualOptionValue();
                    break;
                }
            }
            //映射结束

            Integer hostDeviceId = devicePo.getHostDeviceId()==null||devicePo.getHostDeviceId()==0?devicePo.getId():devicePo.getHostDeviceId();
            String topic = "/down2/control/" + hostDeviceId;
            String funcNo = deviceFuncVo.getFuncNo();
            if(funcNo != null){
                stringRedisTemplate.opsForValue().set("sendFunc." + funcNo, "wait");
                stringRedisTemplate.expire("sendFunc." + funcNo,30, TimeUnit.MINUTES);
            }
            String requestId = funcNo ==null?UUID.randomUUID().toString().replace("-", ""): funcNo;
            DeviceOperLogPo deviceOperLogPo = new DeviceOperLogPo();
            deviceOperLogPo.setFuncId(funcId);
            deviceOperLogPo.setDeviceId(devicePo.getId());
            deviceOperLogPo.setOperType(operType);
            deviceOperLogPo.setOperUserId(userId);
            deviceOperLogPo.setFuncValue(deviceFuncVo.getValue());
            deviceOperLogPo.setRequestId(requestId);
            deviceOperLogPo.setCreateTime(System.currentTimeMillis());
            deviceOperLogMapper.insert(deviceOperLogPo);
            FuncListMessage funcListMessage = new FuncListMessage();
            funcListMessage.setMsg_type("control");
            funcListMessage.setMsg_id(requestId);
            FuncItemMessage funcItemMessage = new FuncItemMessage();
            funcItemMessage.setType(funcId);
            funcItemMessage.setValue(actualValue);
            funcItemMessage.setChildid(devicePo.getChildId());
            funcListMessage.setDatas(Lists.newArrayList(funcItemMessage));
            log.info("sendFunc发送指令 = {}",funcListMessage);
            mqttSendService.sendMessage(topic, JSON.toJSONString(funcListMessage),devicePo.isOldDevice());
            //如果开关为双指令，特殊处理
            if(StringUtils.equals(funcItemMessage.getType(),"ON")){
                stringRedisTemplate.opsForHash().put("control2." + devicePo.getId(), "OFF", "0");
            }else if (StringUtils.equals(funcItemMessage.getType(),"OFF")){
                stringRedisTemplate.opsForHash().put("control2." + devicePo.getId(), "ON", "0");
            }
            stringRedisTemplate.opsForHash().put("control2." + devicePo.getId(), funcItemMessage.getType(), String.valueOf(funcItemMessage.getValue()));
            //stringRedisTemplate.expire("control2." + devicePo.getId(),30, TimeUnit.MINUTES);
            return requestId;
        }
        return "";
    }

    public void flushCache() {
        customerMapper.flushCache();
        //customerUserMapper.flushCache();//暂时只在api里有插入修改动作，无需接口刷新缓存。暂时未开启缓存。
        deviceAbilityMapper.flushCache();
        deviceAbilityOptionMapper.flushCache();
        deviceModelMapper.flushCache();
        deviceModelAbilityMapper.flushCache();
        deviceModelAbilityOptionMapper.flushCache();
    }
    private void getIndexData(DeviceDetailVo deviceDetailVo, Integer deviceId, Integer deviceTypeId) {

        Map<Object, Object> datas = stringRedisTemplate.opsForHash().entries("sensor2." + deviceId);
        Map<Object, Object> controlDatas = stringRedisTemplate.opsForHash().entries("control2." + deviceId);

        DeviceDetailVo.PmDataItem pm = new DeviceDetailVo.PmDataItem();
        pm.setData(getData(datas, SensorTypeEnums.PM25_IN.getCode()));
        pm.setUnit(SensorTypeEnums.PM25_IN.getUnit());
        String data = pm.getData();
        if (StringUtils.isNotEmpty(data)) {
            Integer diData = Integer.valueOf(data);
            if (diData >= 0 && diData <= 35) {
                pm.setMass("优");
            } else if (diData > 35 && diData <= 75) {
                pm.setMass("良");
            } else if (diData > 75 && diData <= 150) {
                pm.setMass("中");
            } else {
                pm.setMass("差");
            }
        } else {
            pm.setMass("");
        }
        deviceDetailVo.setPm(pm);

        DeviceDetailVo.SysDataItem co2 = new DeviceDetailVo.SysDataItem();
        co2.setData(getData(datas, SensorTypeEnums.CO2_IN.getCode()));
        co2.setUnit(SensorTypeEnums.CO2_IN.getUnit());
        deviceDetailVo.setCo2(co2);


        DeviceDetailVo.SysDataItem tvoc = new DeviceDetailVo.SysDataItem();
        tvoc.setUnit(SensorTypeEnums.TVOC_IN.getUnit());
        String tvocData = getData(datas, SensorTypeEnums.TVOC_IN.getCode());
        if (StringUtils.isNotEmpty(tvocData)) {
            Integer digData = Integer.valueOf(tvocData);
            tvoc.setData(FloatDataUtil.getFloat(digData));
        } else {
            tvoc.setData("0");
        }
        deviceDetailVo.setTvoc(tvoc);

        DeviceDetailVo.SysDataItem hcho = new DeviceDetailVo.SysDataItem();
        hcho.setUnit(SensorTypeEnums.HCHO_IN.getUnit());
        String hchoData = getData(datas, SensorTypeEnums.HCHO_IN.getCode());
        if (StringUtils.isNotEmpty(hchoData)) {
            Integer digData = Integer.valueOf(hchoData);
            hcho.setData(FloatDataUtil.getFloat(digData));
        } else {
            hcho.setData("0");
        }
        deviceDetailVo.setHcho(hcho);

        DeviceDetailVo.SysDataItem tem = new DeviceDetailVo.SysDataItem();
        tem.setData(getData(datas, SensorTypeEnums.TEMPERATURE_IN.getCode()));
        tem.setUnit(SensorTypeEnums.TEMPERATURE_IN.getUnit());
        deviceDetailVo.setTem(tem);


        DeviceDetailVo.SysDataItem hum = new DeviceDetailVo.SysDataItem();
        hum.setData(getData(datas, SensorTypeEnums.HUMIDITY_IN.getCode()));
        hum.setUnit(SensorTypeEnums.HUMIDITY_IN.getUnit());
        deviceDetailVo.setHum(hum);

        DeviceDetailVo.SysDataItem remain = new DeviceDetailVo.SysDataItem();
        remain.setData(getData(controlDatas, FuncTypeEnums.TIMER_REMAIN.getCode()));
        remain.setUnit("秒");
        deviceDetailVo.setRemain(remain);

        DeviceDetailVo.SysDataItem screen = new DeviceDetailVo.SysDataItem();
        String time = getData(controlDatas, FuncTypeEnums.TIMER_SCREEN.getCode());
        if (StringUtils.isNotEmpty(time)) {
            screen.setData(String.valueOf(unit * Integer.valueOf(time)));
        } else {
            screen.setData("0");
        }
        screen.setUnit("秒");
        deviceDetailVo.setScreen(screen);


        DeviceDetailVo.DataItem modeItem = new DeviceDetailVo.DataItem();
        modeItem.setChoice(FuncTypeEnums.MODE.getRange());
        modeItem.setType(FuncTypeEnums.MODE.getCode());
        String modeValue = getData(controlDatas, FuncTypeEnums.MODE.getCode());
        modeItem.setValue(modeValue);

        deviceDetailVo.setModeItem(modeItem);

        DeviceTypePo deviceTypePo = deviceTypeMapper.selectById(deviceTypeId);
        if (deviceTypePo != null) {
            //typeId 》abilityId
            List<DeviceAbilityPo> deviceabilityPos = deviceAbilityMapper.selectDeviceAbilitysByTypeId(deviceTypeId);
            List<String> winds = getType(FuncTypeEnums.WIND1.getCode().substring(0, 2), deviceabilityPos);
            List<DeviceDetailVo.OtherItem> dataItems = winds.stream().map(wind -> {
                DeviceDetailVo.OtherItem dataItem = new DeviceDetailVo.OtherItem();
                dataItem.setType(wind);
                StringBuilder choiceSb = new StringBuilder();
                String[] dataArray = {"一", "二", "三", "四", "五", "六", "七"};
                for (int i = 0; i < speed; i++) {
                    choiceSb.append((i + 1)).append(":").append(dataArray[i]).append("档风速");
                    if (i != (speed - 1)) {
                        choiceSb.append(",");
                    }
                }
                dataItem.setChoice(choiceSb.toString());
                dataItem.setValue(getData(controlDatas, wind));
                if (winds.size() == 1) {
                    dataItem.setName("风速");
                } else {
                    dataItem.setName(FuncTypeEnums.getByCode(wind).getMark());
                }
                return dataItem;
            }).collect(Collectors.toList());
            deviceDetailVo.setWindItems(dataItems);
            List<JSONArray> jsonArrays = Lists.newArrayList();
            List<String> uvList = getType(FuncTypeEnums.UV.getCode().substring(0, 2), deviceabilityPos);
            if (uvList.size() > 0) {
                List<DeviceDetailVo.OtherItem> uvItems = uvList.stream().map(uv -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(uv).getMark());
                    otherItem.setType(uv);
                    otherItem.setValue(getData(controlDatas, uv));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray uv = new JSONArray();
                uv.addAll(uvItems);
                jsonArrays.add(uv);
            }

            List<String> screens = getType(FuncTypeEnums.TIMER_SCREEN.getCode().substring(0, 2), deviceabilityPos);
            if (screens.size() > 0) {
                List<DeviceDetailVo.DataItem> screentItems = screens.stream().map(screenStr -> {
                    DeviceDetailVo.DataItem screen1 = new DeviceDetailVo.DataItem();
                    screen1.setValue(getData(controlDatas, screenStr));
                    screen1.setType(screenStr);
                    screen1.setChoice("0");
                    return screen1;
                }).collect(Collectors.toList());
                deviceDetailVo.setScreens(screentItems);
            }

            List<String> anoins = getType(FuncTypeEnums.ANION.getCode().substring(0, 2), deviceabilityPos);
            if (anoins.size() > 0) {
                List<DeviceDetailVo.OtherItem> anoinsItems = anoins.stream().map(anoin -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(anoin).getMark());
                    otherItem.setType(anoin);
                    otherItem.setValue(getData(controlDatas, anoin));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(anoinsItems);
                jsonArrays.add(array);
            }

            List<String> warms = getType(FuncTypeEnums.WARM.getCode().substring(0, 2), deviceabilityPos);
            if (warms.size() > 0) {
                List<DeviceDetailVo.OtherItem> warmItems = warms.stream().map(warm -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(warm).getMark());
                    otherItem.setType(warm);
                    otherItem.setValue(getData(controlDatas, warm));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(warmItems);
                jsonArrays.add(array);
            }

            List<String> humList = getType(FuncTypeEnums.HUMIDIFER.getCode().substring(0, 2), deviceabilityPos);
            if (humList.size() > 0) {
                List<DeviceDetailVo.OtherItem> humItems = humList.stream().map(humStr -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(humStr).getMark());
                    otherItem.setType(humStr);
                    otherItem.setValue(getData(controlDatas, humStr));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(humItems);
                jsonArrays.add(array);
            }

            List<String> deHumList = getType(FuncTypeEnums.DEHUMIDIFER.getCode().substring(0, 2), deviceabilityPos);
            if (deHumList.size() > 0) {
                List<DeviceDetailVo.OtherItem> dehumItems = deHumList.stream().map(dehum -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(dehum).getMark());
                    otherItem.setType(dehum);
                    otherItem.setValue(getData(controlDatas, dehum));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(dehumItems);
                jsonArrays.add(array);
            }

            List<String> valves = getType(FuncTypeEnums.VALVE1.getCode().substring(0, 2), deviceabilityPos);
            if (valves.size() > 0) {
                List<DeviceDetailVo.OtherItem> valvesItems = valves.stream().map(valve -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    if (valves.size() == 1) {
                        otherItem.setName("循环阀");
                    } else {
                        otherItem.setName(FuncTypeEnums.getByCode(valve).getMark());
                    }
                    otherItem.setType(valve);
                    otherItem.setValue(getData(controlDatas, valve));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(valvesItems);
                jsonArrays.add(array);
            }

            List<String> frankList = getType(FuncTypeEnums.FRANKLINISM.getCode().substring(0, 2), deviceabilityPos);
            if (frankList.size() > 0) {
                List<DeviceDetailVo.OtherItem> frankItems = frankList.stream().map(frank -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(frank).getMark());
                    otherItem.setType(frank);
                    otherItem.setValue(getData(controlDatas, frank));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(frankItems);
                jsonArrays.add(array);
            }

            List<String> heatList = getType(FuncTypeEnums.HEAT.getCode().substring(0, 2), deviceabilityPos);
            if (heatList.size() > 0) {
                List<DeviceDetailVo.OtherItem> heatItems = heatList.stream().map(heat -> {
                    DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                    otherItem.setName(FuncTypeEnums.getByCode(heat).getMark());
                    otherItem.setType(heat);
                    otherItem.setValue(getData(controlDatas, heat));
                    return otherItem;
                }).collect(Collectors.toList());
                JSONArray array = new JSONArray();
                array.addAll(heatItems);
                jsonArrays.add(array);
            }
            deviceDetailVo.setFuncs(jsonArrays);

            List<DeviceDetailVo.OtherItem> timers = Lists.newArrayList();
            deviceDetailVo.setTimers(timers);
            deviceDetailVo.setFuncs(jsonArrays);

            List<String> openList = getType(FuncTypeEnums.TIMER_OEPN.getCode().substring(0, 2), deviceabilityPos);
            if (openList.size() > 0) {
                String open = openList.get(0);
                DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                otherItem.setName(FuncTypeEnums.getByCode(open).getMark());
                otherItem.setType(open);
                data = getData(controlDatas, open);
                if (StringUtils.isNotEmpty(data)) {
                    otherItem.setValue(getData(controlDatas, open));
                } else {
                    otherItem.setValue("0");
                }
                timers.add(otherItem);
            }

            List<String> closeList = getType(FuncTypeEnums.TIMER_CLOSE.getCode().substring(0, 2), deviceabilityPos);
            if (closeList.size() > 0) {
                String close = closeList.get(0);
                DeviceDetailVo.OtherItem otherItem = new DeviceDetailVo.OtherItem();
                otherItem.setName(FuncTypeEnums.getByCode(close).getMark());
                otherItem.setType(close);
                data = getData(controlDatas, close);
                if (StringUtils.isNotEmpty(data)) {
                    otherItem.setValue(getData(controlDatas, close));
                } else {
                    otherItem.setValue("0");
                }
                timers.add(otherItem);
            }
        }
        DeviceDetailVo.DataItem childItem = new DeviceDetailVo.DataItem();
        childItem.setType(FuncTypeEnums.CHILD_LOCK.getCode());
        childItem.setChoice("0:未开,1:已开");
        childItem.setValue(getData(controlDatas, FuncTypeEnums.CHILD_LOCK.getCode()));
        deviceDetailVo.setChildItem(childItem);
    }

    private List<String> getType(String smallType, List<DeviceAbilityPo> deviceabilityPos) {
        List<String> retList = Lists.newArrayList();
        for (DeviceAbilityPo deviceabilityPo : deviceabilityPos) {
            if (deviceabilityPo.getDirValue().startsWith(smallType)) {
                retList.add(deviceabilityPo.getDirValue());
            }
        }
        return retList;
    }

    private String getData(Map<Object, Object> map, String key) {
        if (map.containsKey(key)) {
            return (String) map.get(key);
        }
        return "0";
    }

    private static int getAqi(Integer pm2_5) {
        float[] tbl_aqi = {0f, 50f, 100f, 150f, 200f, 300f, 400f, 500f};
        float[] tbl_pm2_5 = {0f, 35f, 75f, 115f, 150f, 250f, 350f, 500f};
        int i;
        if (pm2_5 > tbl_pm2_5[7]) {
            return (int) tbl_aqi[7];
        }
        for (i = 0; i < 8 - 1; i++) {
            if ((pm2_5 >= tbl_pm2_5[i]) && (pm2_5 < tbl_pm2_5[i + 1])) {
                break;
            }
        }
        return (int) (((tbl_aqi[i + 1] - tbl_aqi[i]) / (tbl_pm2_5[i + 1] - tbl_pm2_5[i]) * (pm2_5 - tbl_pm2_5[i]) + tbl_aqi[i]));
    }

    /*public boolean verifyUser(Integer userId, Integer deviceId) {
        DevicePo devicePo = deviceMapper.selectById(deviceId);
        Integer hostDeviceId = devicePo.getHostDeviceId();
        CustomerUserPo customerUserPo = customerUserMapper.selectById(userId);
        String wxOpenId = customerUserPo.getOpenId();
        DeviceCustomerUserRelationPo deviceCustomerUserRelationPo = new DeviceCustomerUserRelationPo();
        deviceCustomerUserRelationPo.setOpenId(wxOpenId);
        if(hostDeviceId != null){
            deviceCustomerUserRelationPo.setDeviceId(hostDeviceId);
        }else{
            deviceCustomerUserRelationPo.setDeviceId(deviceId);
        }
        Integer count = deviceCustomerUserRelationMapper.queryRelationCount(deviceCustomerUserRelationPo);
        if (count > 0) {
            return true;
        }
        return false;
    }*/
}
